package com.admin.application;

import com.admin.domain.modle.Order;
import com.admin.domain.modle.OrderSeat;
import com.admin.domain.repository.OrderRepository;
import com.admin.infrastructure.RemoteDataUtil;
import com.admin.interfaces.facade.dto.OrderQueryDTO;
import com.admin.utils.HaiyinException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.UUID;

/**
 * description User: WeiDa Date: 2017-4-11 Time: 16:45
 */
@Service
@CacheConfig(cacheNames = "order")
public class OrderService {

	private static final Logger LOGGER = LoggerFactory
			.getLogger(OrderService.class);
	@Autowired
	protected OrderRepository orderRepository;

	@Caching(put = @CachePut(key = "#order.id"), evict = @CacheEvict(key = "'list'"))
	public Order create(Order order) {
		order.setId(UUID.randomUUID().toString());
		orderRepository.add(order);
		return order;
	}

	@Caching(put = @CachePut(key = "#order.id"), evict = @CacheEvict(key = "'list'"))
	public Order modify(Order order) {
		orderRepository.update(order);
		return order;
	}

	@Cacheable
	public Order get(String code) {
		return orderRepository.get(code);
	}

	public Order detail(String id) {
		return orderRepository.get(id);
	}

	public List<Order> list(OrderQueryDTO queryDTO) {
		return orderRepository.list(queryDTO);
	}

	public void delete(String code) {
		orderRepository.remove(code);
	}

	public Order findById(int orderId) {
		Order order = orderRepository.getOrder(orderId);
		if (order == null) {
			throw new HaiyinException("order notfound");
		}
		List<OrderSeat> seats = orderRepository.getOrderSeats(orderId);
		order.setSeats(seats);
		return order;
	}

	@Transactional
	public void preCreate(Order order) {
		// precheck...
		if (order == null) {
			throw new HaiyinException("order not be empty");
		}
		if (order.getPlayId() == null) {
			throw new HaiyinException("playId not be empty");
		}
		if (order.getOrderId() == null) {
			throw new HaiyinException("orderId not be empty");
		}
		if (StringUtils.isBlank(order.getPlayName())) {
			throw new HaiyinException("playName not be empty");
		}
		/*
		 * if (StringUtils.isBlank(order.getPlayCode())) { throw new
		 * HaiyinException("playCode not be empty"); }
		 */
		if (StringUtils.isBlank(order.getPlayDate())) {
			throw new HaiyinException("playDate not be empty");
		}
		if (StringUtils.isBlank(order.getOpenId())) {
			throw new HaiyinException("openId not be empty");
		}
		/*if (StringUtils.isBlank(order.getNickName())) {
			throw new HaiyinException("nickName请先关注公众号");
		}*/
		if (CollectionUtils.isEmpty(order.getSeats())) {
			throw new HaiyinException("seats not be empty");
		}
		double amount = 0d;
		for (OrderSeat os : order.getSeats()) {
			if (os.getSeatId() == null || StringUtils.isBlank(os.getName())
					|| os.getPrice() <= 0d) {
				throw new HaiyinException("选座信息有误");
			}
			os.setOrderId(order.getOrderId());
			amount += os.getPrice();
		}
		order.setQuantity(order.getSeats().size());
		order.setPayAmount(amount);
		// delete order_seta
		orderRepository.deleteSeat(order.getOrderId().intValue());
		// upsert order
		orderRepository.upsert(order);
		// insert seats
		orderRepository.saveSeats(order.getSeats());
	}

	public void postCreate(int orderId, String tradeNo, String uname,
			String phone) {
		if (StringUtils.isBlank(tradeNo)) {
			throw new HaiyinException("tradeNo not be empty");
		}
		if (StringUtils.isBlank(uname)) {
			throw new HaiyinException("uname not be empty");
		}
		if (StringUtils.isBlank(phone)) {
			throw new HaiyinException("phone not be empty");
		}
		int result = orderRepository.updateWhenPaying(orderId, tradeNo, uname,
				phone);
		if (result != 1) {
			throw new HaiyinException("order data invalid");
		}
	}

	public void postPayment(com.foxinmy.weixin4j.payment.mch.Order order) {
		// TODO 这里可以记录流水
		Integer orderId = Integer.parseInt(order.getAttach());
		LOGGER.warn("weixin order"+orderId);
		Order localOrder = orderRepository.getOrder(orderId);
		boolean confirm = RemoteDataUtil.postHaiyinOrderPay(orderId,localOrder.getName(),localOrder.getPhone(),localOrder.getTradeNo());
		if (!confirm) {
			throw new HaiyinException("order data invalid : 确认远程支付订单失败，请联系客服");
		}
		orderRepository.updateWhenPaid(order.getOutTradeNo(),
				order.getFormatTimeEnd());
		LOGGER.info("订单确认 {} -> {}", order, confirm);
	}

	public int cancelOrder(int orderId) {
		boolean cancel = RemoteDataUtil.postHaiyinOrderCancel(orderId);
		if (!cancel) {
		    LOGGER.error("取消订单失败"+orderId,orderId);
			throw new HaiyinException("order data invalid : 取消订单失败+"+orderId);
		}
		return orderRepository.cancelOrder(orderId);
	}

	@Transactional
	public void deleteOrder(int orderId) {
		orderRepository.delete(orderId);
		orderRepository.deleteSeat(orderId);
	}

	public int updateRemark(String id, String remark) {
		return orderRepository.updateRemark(id, remark);
	}

	public List<Order> listByStatus(String status) {
		return orderRepository.listByStatus(status);
	}

	public List<Order> listByStatusAndUserId(String status,String userId) {
		return orderRepository.listByStatusAndUserId(status,userId);
	}


	public int verifyOrder(int orderId) {
		boolean verify = RemoteDataUtil.postHaiyinOrderIsWriteOff(orderId);
		if (!verify) {
			LOGGER.error("核销订单失败"+orderId,orderId);
			throw new HaiyinException("order data invalid : 核销订单失败:"+orderId);
		}
		return orderRepository.verifyOrder(orderId);
	}
}
